跳到主要内容

定制现有的示例应用程序

对现有的示例应用程序进行调试和优化,以满足特定的用例要求。本节将指导您在运行 Canonical Ubuntu 的魔方派 3 目标设备上使用 Qualcomm® 智能多媒体产品 (QIMP) SDK 下载、构建、自定义源代码,从而完全控制应用程序行为并实现跨运行时环境的性能优化。

预构建的应用程序非常适合快速评估,而定制化开发可实现:

  • 集成自己的模型、媒体或逻辑
  • 针对特定运行时目标(CPU、GPU、NPU)优化性能
  • 添加新功能修改现有功能以符合您的用例
  • 使用 GStreamer尝试不同的管道配置
  • 从工作基线开始构建可用于生产环境的应用程序

前提条件

  • Ubuntu 操作系统 已刷入。
  • 具有适当权限的终端访问
  • 如果您之前没有安装过 PPA 包,请按照以下步骤进行安装。
      git clone -b ubuntu_setup --single-branch https://github.com/rubikpi-ai/rubikpi-script.git 
    cd rubikpi-script
    ./install_ppa_pkgs.sh

从源代码构建

按照以下步骤下载、配置和编译示例应用程序源代码。这样就可以根据需要修改应用程序行为并集成自定义逻辑。

1️⃣安装以下软件包以下载源代码。

sudo apt-add-repository -s ppa:ubuntu-qcom-iot/qcom-ppa
sudo apt-get install adreno-dev
sudo apt-get install gstreamer1.0-qcom-sample-apps-utils-dev

2️⃣构建依赖项
运行命令获取源代码编译所需的插件

sudo apt build-dep gst-plugins-qti-oss

3️⃣下载源代码
下载示例应用程序源代码

cd /home/ubuntu
sudo apt source gst-plugins-qti-oss

4️⃣示例应用程序代码详解
以 gst-ai-usb-camera-app 为例进行代码讲解。这是高通开发的基于 GStreamer 的 C 语言应用程序,用于演示如何将 USB 摄像头用于不同用途:

  • 在显示器上显示实时视频
  • 将视频保存到文件
  • 通过 RTSP 流式传输视频
  • 使用 AI 模型运行对象检测

gst-ai-usb-camera-app 的源代码在

cd gst-plugins-qti-oss/gst-sample-apps/gst-ai-usb-camera-app

详细信息
a: 头文件和常量

#include <glib-unix.h>
#include <stdio.h>
#include <gst/gst.h>
#include <linux/videodev2.h>
#include <sys/ioctl.h>
#include <json-glib/json-glib.h>

文件和常量提供以下支持:

  • GLib:实用函数和主循环
  • GStreamer:多媒体框架
  • Video4Linux2 (V4L2):访问 USB 摄像头
  • JSON-GLib:从 JSON 读取配置

然后我们定义默认值:

#define DEFAULT_WIDTH 1280
#define DEFAULT_HEIGHT 720
#define DEFAULT_FRAMERATE 30
#define DEFAULT_OUTPUT_FILENAME "/etc/media/video.mp4"
#define DEFAULT_IP "127.0.0.1"
#define DEFAULT_PORT "8900"

如果用户不提供自定义设置,则使用这些设置。

b. 应用程序上下文结构
GstCameraAppCtx
此结构保存应用程序的状态:

struct GstCameraAppCtx {
GstElement *pipeline;
GMainLoop *mloop;
gchar *output_file;
gchar *ip_address;
gchar *port_num;
gchar *enable_ml;
gchar dev_video[16];
enum GstSinkType sinktype;
enum GstVideoFormat video_format;
gint width;
gint height;
gint framerate;
};

GstAppOptions
此结构保存来自配置文件的用户定义选项:

typedef struct {
gchar *file_path;
gchar *model_path;
gchar *labels_path;
gchar *constants;
gchar **snpe_layers;
GstCameraSourceType camera_type;
GstModelType model_type;
GstYoloModelType yolo_model_type;
gdouble threshold;
gint delegate_type;
gint snpe_layer_count;
gboolean use_cpu;
gboolean use_gpu;
gboolean use_dsp;
} GstAppOptions;

c. 从 JSON 读取配置
函数parse_json() 读取配置文件,并将值设置到appctx和options。
配置示例:

{
"width": 1280,
"height": 720,
"framerate": 30,
"output": "waylandsink",
"enable-object-detection": "TRUE",
"yolo-model-type": "yolov8",
"ml-framework": "tflite"
}

代码片段:

if (json_object_has_member(root_obj, "width")) {
appctx->width = json_object_get_int_member(root_obj, "width");
}

此代码实现从配置文件读取摄像头分辨率宽度参数。

d. 查找 USB 摄像头
函数: find_usb_camera_node()
该函数循环遍历 /dev/video0 到 /dev/video63 来查找有效的 USB 摄像头。

while (idx < MAX_VID_DEV_CNT) {
snprintf(appctx->dev_video, sizeof(appctx->dev_video), "/dev/video%d", idx);
mFd = open(appctx->dev_video, O_RDWR);
ioctl(mFd, VIDIOC_QUERYCAP, &v2cap);
if (strcmp((const char *)v2cap.driver, "uvcvideo") == 0) {
break;
}
idx++;
}

e. 创建 GStreamer 管道
函数: create_preview_pipe()
该函数根据输出类型(显示、文件或 RTSP)构建管道。
示例:实时预览
v4l2src → capsfilter → waylandsink
代码:

v4l2src = gst_element_factory_make("v4l2src", "v4l2src");
capsfilter = gst_element_factory_make("capsfilter", "capsfilter");
waylandsink = gst_element_factory_make("waylandsink", "waylandsink");

示例:保存到文件
v4l2src → capsfilter → qtivtransform → v4l2h264enc → h264parse → filesink
代码:

filesink = gst_element_factory_make("filesink", "filesink");
v4l2h264enc = gst_element_factory_make("v4l2h264enc", "v4l2h264enc");
h264parse = gst_element_factory_make("h264parse", "h264parse");

示例:RTSP 流式传输
v4l2src → capsfilter → qtivtransform → v4l2h264enc → h264parse → qtirtspbin

f. 对象检测管道
函数: create_pipe()
这将构建一个更复杂的管道,用于基于 AI 的对象检测。
管道流程:
v4l2src → capsfilter → tee → qtivcomposer → waylandsink
代码:

qtimlvconverter = gst_element_factory_make("qtimlvconverter", "qtimlvconverter");
qtimlelement = gst_element_factory_make("qtimltflite", "qtimlelement");
qtimlvdetection = gst_element_factory_make("qtimlvdetection", "qtimlvdetection");
qtivcomposer = gst_element_factory_make("qtivcomposer", "qtivcomposer");

插件功能如下:
预处理:qtimlvconverter
推理:qtimltflite, qtimlsnpe, or qtimlqnn
后处理:qtimlvdetection
叠加:qtivcomposer

g. 主函数
程序入口:

int main(int argc, char *argv[]) {
appctx = gst_app_context_new();
parse_json(config_file, &options, appctx);
find_usb_camera_node(appctx);
create_pipe(appctx, &options);
gst_element_set_state(pipeline, GST_STATE_PAUSED);
g_main_loop_run(appctx->mloop);
}

它的功能:
初始化应用程序上下文
读取配置文件
查找 USB 摄像头
构建管道
运行主循环

h. 用户可以根据以下内容来更新示例应用程序

  • 根据上述解释
  • 获取图片格式与尺寸 获取所连接 USB 摄像头支持的图像格式和大小的详细信息(通过yavta),并修改json或源代码。

5️⃣编译示例应用程序工具以获取最新的头文件

cd gst-plugins-qti-oss/gst-sample-apps/gst-sample-apps-utils
mkdir build; cd build
cmake \
-DGST_VERSION_REQUIRED=1.20.1 \
-DSYSROOT_INCDIR=/usr/include \
-DSYSROOT_LIBDIR=/usr/lib \
-DGST_PLUGINS_QTI_OSS_INSTALL_BINDIR=/usr/bin \
-DGST_PLUGINS_QTI_OSS_INSTALL_CONFIG=/etc/configs \
-DENABLE_CAMERA=TRUE \
-DENABLE_VIDEO_ENCODE=TRUE \
-DENABLE_VIDEO_DECODE=TRUE \
-DENABLE_DISPLAY=TRUE \
-DENABLE_ML=TRUE \
-DENABLE_AUDIO=TRUE \
-DCAMERA_SERVICE=LECAM \
-DGST_PLUGINS_QTI_OSS_INSTALL_INCDIR=/usr/include \
..
make
make install

6️⃣进入您想要修改的示例应用程序,应用您的更改并进行编译。此示例展示如何构建对象检测应用程序。

cd gst-plugins-qti-oss/gst-sample-apps/gst-ai-object-detection
mkdir build; cd build
cmake \
-DGST_VERSION_REQUIRED=1.20.1 \
-DSYSROOT_INCDIR=/usr/include \
-DSYSROOT_LIBDIR=/usr/lib \
-DGST_PLUGINS_QTI_OSS_INSTALL_BINDIR=/usr/bin \
-DGST_PLUGINS_QTI_OSS_INSTALL_CONFIG=/etc/configs \
-DENABLE_CAMERA=TRUE \
-DENABLE_VIDEO_ENCODE=TRUE \
-DENABLE_VIDEO_DECODE=TRUE \
-DENABLE_DISPLAY=TRUE \
-DENABLE_ML=TRUE \
-DENABLE_AUDIO=TRUE \
-DCAMERA_SERVICE=LECAM \
-DGST_PLUGINS_QTI_OSS_INSTALL_INCDIR=/usr/include \
..
make
make install
备注

每个示例应用程序都需要单独编译

7: 运行已编译的示例应用程序

gst-ai-usb-camera-app

要显示可用的帮助选项,请在 SSH shell 中运行以下命令:

gst-ai-usb-camera-app -h

CTRL + C可停止用例。

参考文档:

AI developer workflow - Ubuntu on Qualcomm® IoT Platforms Documentation